package com.glg.javadoc_searcher;

import org.ansj.domain.Term;
import org.ansj.splitWord.analysis.ToAnalysis;

import javax.print.Doc;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Scanner;

// 通过这个类，来完成整个的搜索过程
public class DocSearcher {

    // 此处要加上索引对象的实例
    // 同时要完成索引加载的工作（这样才能将文件里面的索引加到内存中，不然内存中没有东西查）
    private Index index = new Index();

    public DocSearcher() {
        index.load();
    }

    // 完成整个搜索过程的方法
    // 参数（输入部分）就是用户给出的查询词
    // 返回值（输出部分）就是搜索结果的集合
    public List<Result> search(String query){
        // 1. [分词] 针对 query 这个查询词进行分词
        List<Term> terms = ToAnalysis.parse(query).getTerms();

        // 2. [触发] 针对分词结果来查倒排
        List<Weight> allTermResult = new ArrayList<>();
        for(Term term : terms) {
            String word = term.getName();
            // 虽然倒排索引中有很多的词，但是这里的词一定都是之前的文档中存在的
            List<Weight> invertedList = index.getInverted(word);
            if(invertedList == null) {
                // 说明这个词在所有文档中都不存在
                continue;
            }
            // 对我们的每一个倒排拉链进行汇总
            allTermResult.addAll(invertedList);
        }

        // 3. [排序] 针对触发的结果按照权重降序排序
        allTermResult.sort(new Comparator<Weight>() {
            @Override
            public int compare(Weight o1, Weight o2) {
                // 如果是升序排序：return o1.getWeight() - o2.getWeight();
                // 如果是降序排序：return o2.getWeight() - o1.getWeight();
                return o2.getWeight() - o1.getWeight();
            }
        });

        // 4. [包装结果] 针对排序的结果，去查正排，构造出要返回的数据
        List<Result> results = new ArrayList<>();
        for(Weight weight : allTermResult){
            DocInfo docInfo = index.getDocInfo(weight.getDocId());
            Result result = new Result();
            result.setTitle(docInfo.getTitle());
            result.setUrl(docInfo.getUrl());
            result.setDesc(GenDesc(docInfo.getContent(), terms));
            results.add(result);
        }
        return results;
    }




    private String GenDesc(String content, List<Term> terms) {
        int firstPos = -1;
        // 先遍历分词结果，看看哪个结果是在 content 中存在
        for(Term term : terms) {
            // 分词库直接针对词进行转小写了
            // 正因如此，就必须把正文也先转成小写，然后再查询
            String word = term.getName();
            // 此处需要的是 “全字匹配”，让 word 能够独立成词，才要查找出来，而不是只作为词的一部分(左右加空格)
            firstPos = content.toLowerCase().indexOf(" " + word + " ");
            if(firstPos >= 0){
                // 找到了位置
                break;
            }
        }
        // 所有的分词结果都不在正文中存在（标题中触发）
        if(firstPos == -1) {
            // 此时就直接返回一个空的描述，或者也可以直接取正文的前 160 个字符
            // return null;
            return content.substring(0, 160) + "...";
        }
        // 从 firstPos 作为基准位置，往前找 60 个字符，作为描述的起始位置
        String desc = "";
        int descBeg = firstPos < 60 ? 0 : firstPos - 60;  // 不足 60 个字符，就直接从 0 开始读
        if(descBeg + 160 > content.length()) {
            desc = content.substring(descBeg); // 从 descBeg 截取到末尾
        }else {
            desc = content.substring(descBeg, descBeg + 160) + "...";
        }
        return desc;
    }

    public static void main(String[] args) {
        DocSearcher docSearcher = new DocSearcher();
        Scanner scanner = new Scanner(System.in);
        while (true) {
            System.out.println("-> ");
            String query = scanner.next();
            List<Result> results = docSearcher.search(query);
            for (Result result : results) {
                System.out.println("======================");
                System.out.println(result);
            }
        }
    }
}









